
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
 
void OneUTF82Unicode(const char* utf_char, char* unicode_char);
 
char* utf82unicode(const char* utf,size_t *unicode_number)
{    
    char* utf8 = strdup(utf);
    size_t utf8_length = strlen(utf8); 
    //这里可以自己考虑实现更精确的大小.
    //+2是留两个00.
    char* unicode = (char*)malloc(utf8_length*2+2);
    memset(unicode,0,utf8_length*2+2);
    size_t index  = 0;
    size_t start = 0;
    unsigned char temp;
    //10000000=0x80 1110=0xE 110=0x6
    unsigned char flag = 0;
    size_t unicode_index = 0;
    bool is_finded = false;
    while((temp = utf8[index]))
    {
        start = index;
 
        temp = temp >> 4 ;
        if(temp > 0xE)
        {
            assert(0);
            printf("utf8 bigger than 4 byte is not supported.\n");
            break;
        }
 
        if(temp == 0xE)
        {
            index+=3;
            is_finded = true;
        }
 
        temp = temp >> 1;
        if(!is_finded && temp == 0x6)
        {
            index+=2;
            is_finded = true;
        }
 
        temp = temp >> 2;
        if(!is_finded && temp == 0x00)
        {
            index+=1;
            is_finded = true;
        }
 
        if(index > utf8_length)
        {
            break;
        }
        flag = utf8[index];
        utf8[index] = 0;
        OneUTF82Unicode(utf8+start,unicode+unicode_index);
        utf8[index] = flag;
        unicode_index+=2;
        is_finded = false;
    }
    free(utf8);
    *unicode_number = unicode_index/2;
    return unicode;
}
 
void OneUTF82Unicode(const char* utf_char, char* unicode_char)
{
    //unicode: 0x192->110010010 ,utf8:0xC692->11000110|10010010
    //小端序
    int utf_length = strlen(utf_char);
    //0x3F->00111111
    switch(utf_length)
    {
        case 1: 
            unicode_char[0] = utf_char[0];
            unicode_char[1] = 0;
            break;
        case 2: 
            unicode_char[0] = (utf_char[1] & 0x3F) | ((utf_char[0] & 0x3) << 6);
            unicode_char[1] = (utf_char[0] & 0x3C) >> 2;
            break;
        case 3: 
            unicode_char[0] = (utf_char[2] & 0x3F) | ((utf_char[1] & 0x3) << 6);
            unicode_char[1] = ((utf_char[1] & 0x3C) >> 2) | ((utf_char[0] & 0xF) << 4);
            break;
        default:
            assert(0);
            printf("utf_char length is bigger than 4 unsupported.\n");
            break;
    }
}

#ifdef _TEST_
int main(int argc, char *argv[])
{
    char utf_char[12] = {0xC3,0xBE};
    memset(utf_char+2,0,10);
 
    char unicode_char[3] = {0,0,0};
    OneUTF82Unicode(utf_char,unicode_char);
    printf("%x,%x\n",(unsigned char)unicode_char[0],unicode_char[1]);
 
    utf_char[0] = 0xE6;
    utf_char[1] = 0x88;
    utf_char[2] = 0x91;
 
    OneUTF82Unicode(utf_char,unicode_char);
    printf("%x,%x\n",(unsigned char)unicode_char[0],unicode_char[1]);
 
    size_t unicode_number = 0;
    char utf_str[]="测试";
    char* unicode = utf82unicode(utf_str,&unicode_number);
    
	printf("utf-8: 0x%02x,0x%02x,0x%02x,0x%02x\n",(unsigned char)utf_str[0],(unsigned char)utf_str[1],(unsigned char)utf_str[2],(unsigned char)utf_str[3]);        

    printf("%d\n",unicode_number);
    size_t index = 0;
    for(size_t i=0;i<unicode_number;++i,index+=2)
    {
        printf("0x%02x,0x%02x\n",(unsigned char)unicode[index],(unsigned char)unicode[index+1]);        
    }
    free(unicode);
    return 0;
}
#endif